#include <QtGui>
#include <QDir>
#include <QMessageBox>
#include <QDateTime>
#include <QTime>
#include <QIntValidator>
#include <QFileDialog>
#include <QInputDialog>

#include "Qsci/qsciscintilla.h"
#include "qscintilla.h"
#include "mainwindow.h"
#include "editortabwidget.h"
#include "buildlog.h"
#include "build.h"
#include "filebrowser.h"
#include "findwidget.h"
#include "misc.h"
#include "executer.h"
#include "helpwidget.h"
#include "mannasettings.h"
#include "breakpointsmanager.h"
#include "bkptsmanager.h"
#include "settingdlg.h"
#include "meditor.h"
#include "gdbmi.h"
#include "gdbmanager.h"
#include "eventhandler.h"

#include <stdio.h>
#include <unistd.h>


#include "externtool.h"

#ifdef Q_OS_WIN
#include<windows.h>
#include <winuser.h>
#else
#include<sys/stat.h>
#endif

#define TARGET_OUTPUT_LIMIT 1000

#define SUFFIX "_"

MainWindow::MainWindow()
{
    qRegisterMetaType<enum SourceType>("SourceType");
    m_curDirectory = qApp->applicationDirPath();
    installTranslators();

    setupUi(this);
    QFont font("Monospace");
    font.setStyleHint(QFont::Monospace);
    memBrowser->setFont(font);
    m_state = EditMode;

    m_finder = new FindWidget(this);
    m_finder->setWindowFlags(Qt::Tool);
    m_finder->hide();

    createActions();
    createMenus();
    createToolBars();
    createStatusBar();
    connectSignals();

    readSettings();

    for (int i = 0; i < maxRecentsFiles; ++i) {
        m_actionsRecentsFiles[i] = new QAction(this);
        menuRecentFiles->addAction(m_actionsRecentsFiles[i]);
        m_actionsRecentsFiles[i]->setVisible(false);
        connect(m_actionsRecentsFiles[i], SIGNAL(triggered()),this, SLOT(slotOpenRecentFile()));
    }
    loadRecentFiles();

    /*
        Initialize back-end debugger
    */
    QString gcc, fpc, suffix;
    bool show;
    MannaSettings::getMannaSettings()->compilerPath(gcc, fpc, suffix, show);

    m_debugger = new GDBMI (gcc + "/gdb");
    connect (m_debugger, SIGNAL (message (const QString &, int)),
        this, SLOT (setDebugMessage (QString, int)));

    m_defaultClient = new GDBMIDefaultClient (m_debugger, this);
    m_execClient = new GDBMIExecClient (m_debugger);
    m_stackClient = new GDBMIStackClient (m_debugger, callStackList);
    m_variableClient = new GDBMIVariableClient (m_debugger,
        treeLocalWidget, treeWatchWidget);
    m_memoryClient = new GDBMIMemoryClient (m_debugger, memBrowser, addrLine, bytesLine);
    changeRunState(EditMode);

    connect (callStackList, SIGNAL (itemDoubleClicked (QListWidgetItem *)),
        this, SLOT (slotItemDoubleClicked (QListWidgetItem *)));

    m_eventHandler = new MEventHandler (this);

    stopAtMain = false;

    lastStepLine = 0;

    // Open those files that were not closed by user
    MannaSettings *settings = MannaSettings::getMannaSettings();
    settings->beginGroup("OpenedFileList");
        QStringList fs = settings->value("OpenedFiles").toStringList();
        QString lf = settings->value("LastOpenedFile").toString();
    settings->endGroup();

    foreach (QString f, fs) {
        if (QFile(QDir::toNativeSeparators(f)).exists())
            doOpenFile(f);
    }
    if (!lf.isEmpty())
        doOpenFile(lf);

    // Open the file given by command line.
    QStringList args = qApp->arguments();
    args.removeFirst();
    foreach (QString f, args) {
        doOpenFile(QDir::fromNativeSeparators(f));
    }

    if (m_editorTab->currentIndex() != -1) {
        m_editorTab->currentWidget()->setFocus();
    }

    // Set the window accept drag in and drop.
    setAcceptDrops(true);

#ifdef Q_OS_LINUX
    // init the comm channel
    m_timer = new QTimer( this );
    //m_timer->setInterval( 1000 );
    connect(m_timer,SIGNAL( timeout() ), this,
        SLOT( slotlinuxMsg() ));
    m_timer->start( 1000 );
#endif

    m_searchKey = new QLineEdit(this);
    m_searchAction = new QAction(this);
    m_searchAction->setIcon( QIcon(":/images/help/search.png") );

    helpToolbar->addWidget(m_searchKey);
    helpToolbar->addAction(m_searchAction);
    connect (m_searchKey, SIGNAL(returnPressed()), this, SLOT(slotSearchHelpFile()));
    connect (m_searchAction, SIGNAL(triggered()), this, SLOT(slotSearchHelpFile()));
    bytesLine->setValidator(new QIntValidator(this));
}

MainWindow::~MainWindow ()
{
    delete m_debugger;
    delete m_defaultClient;
    delete m_execClient;
    delete m_stackClient;
    delete m_variableClient;
    delete m_memoryClient;
    delete m_eventHandler;
}

//line: the line where the target stop
//bkptno: the breakpoint number where the target stop
void MainWindow::onTargetStop (int line,int bkptno)
{
    lastStepLine = line;
    MEditor *e = m_editorTab->editor (m_activeFileName, true);
    if (e) {
        m_editorTab->setCurrentWidget (e);

        std::list<BKPTPAIR>    bkpt_list;
        bkpt_list.clear();
        if (bkptno > 0) {
            if (m_execClient->getUnnecessaryBreakpoints(line,bkptno,bkpt_list) > 0) {
                bool delBreakpoints = false;
                for (std::list<BKPTPAIR>::iterator it = bkpt_list.begin();it!=bkpt_list.end();++it) {
                    qDebug("line:%d\n",it->first);
                    if (e->toggleBreakpoint(it->first)) {
                        e->toggleBreakpoint(it->first);
                    } else {
                        delBreakpoints = true;
                    }
                }
                if (!m_execClient->breakpointExist(line) && delBreakpoints) {
                    e->toggleBreakpoint(line);
                    QMessageBox::warning (this, PROGRAM_NAME,tr ("One or more breakpoints are not positioned on valid lines.\n"
                    "These breakpoints will be moved to the next valid line."),QMessageBox::Ok);
                }
                //editor->refreshBreakpointsRecord();
            }
        }

        e->setStepMarker (line);
        actionPauseResume->setEnabled(false);

        setButtonState(1);
    } else {
        QMessageBox::warning (this, PROGRAM_NAME,
            QString ("Can NOT open the source file under debug\n\n<b>%1</b>").
                arg (m_activeFileName),
                QMessageBox::Ok);
    }
}

QString MainWindow::gdbstrToUnicode(QString src) {
    char src_char[4096],des_char[4096];
    sprintf(src_char,"%s",src.toLocal8Bit().constData());
    int j = 0;
    for (int i = 0;i < src.length();++i) {
        if (src_char[i] != '\\') {
            des_char[j++] = src_char[i];
        } else {
            unsigned int calc = 0;
            ++i;
            while (src_char[i] >= '0' && src_char[i] < '8') {
                calc *= 8;
                calc += src_char[i] - '0';
                ++i;
            }
            //if (src_char[i] >= '0' && src_char[i] <= '9') { calc += src_char[i] - '0';} else {--i;};
            --i;
            des_char[j++] = calc;
        }
    }
    des_char[j] = '\0';
    return QString::fromLocal8Bit(des_char,j);
}

void MainWindow::onTargetStop (QString fullfilename,int line)
{
    lastStepLine = line;
    //qDebug("onTargetStop fullname");
#ifdef Q_OS_WIN
    fullfilename.replace("//", "/");
    fullfilename.replace(QString("\\\\"),QString("/"));
#endif
    //m_activeFileName = gdbstrToUnicode(fullfilename);
    m_activeFileName = fullfilename;
    //qDebug(m_activeFileName.toLatin1().constData());
    //qDebug(fullfilename.toLatin1().constData());
    MEditor *editor = m_editorTab->editor (m_activeFileName, true);
    if (editor->isModified()) {
        int ret = QMessageBox::warning (this, PROGRAM_NAME,
                    tr ("The source file has been modified, hence the following\n"
                    "information displayed may be incorrect.\n\n"
                    "Press Ok to continue debug anyway\n"
                    "Press Cancel to exit debug"),
                    QMessageBox::Ok | QMessageBox::Cancel,
                    QMessageBox::Cancel);
        if (ret == QMessageBox::Cancel)
        {
            stopDebug ();
            return;
        }
    }
    /*if (QString::compare(fullfilename,m_startFileName)) {
        editor->setReadOnly(true);
    }*/
    m_lastModified = editor->lastModified();

    if (editor) {
        m_editorTab->setCurrentWidget (editor);
        editor->setStepMarker (line);
        actionPauseResume->setEnabled(false);
        setButtonState(1);
    }
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    int ret;
    if (m_state == CompileMode) {
        ret = QMessageBox::warning(this, PROGRAM_NAME,
                    tr("Compile source file...\n"
                    "Do you want to stop compiling file?"),
                    QMessageBox::Yes | QMessageBox::No,
                    QMessageBox::Yes);
        if (ret == QMessageBox::No) {
            event->ignore();
            return;
        } else {
            slotStopCompile();
            qApp->processEvents();
        }
    }
    if (m_state == ExecMode) {
        ret = QMessageBox::warning(this, PROGRAM_NAME,
                    tr("Running target...\n"
                    "Do you want to stop running?"),
                    QMessageBox::Yes | QMessageBox::No,
                    QMessageBox::Yes);
        if (ret == QMessageBox::No) {
            event->ignore();
            return;
        } else {
            slotStopExecute();
            qApp->processEvents();
        }
    }
    if (m_state == DebugMode) {
        ret = QMessageBox::warning(this, PROGRAM_NAME,
                    tr("Debugging target...\n"
                    "Do you want to stop debugging target?"),
                    QMessageBox::Yes | QMessageBox::No,
                    QMessageBox::Yes);
        if (ret == QMessageBox::No) {
            event->ignore();
            return;
        } else {
            stopDebug();
            qApp->processEvents();
        }
    }
    if (maybeSave()) {
        writeSettings();
        /* In order to save each file option. */
        m_editorTab->closeAllTabs(false);
        event->accept();
    } else {
        event->ignore();
        return;
    }
    if (HelpWidget::hasInstance()) {
        HelpWidget::instance()->close();
        qApp->processEvents();
        delete HelpWidget::instance();
    }
    delete HelpWidget::getCHelpNames();
    delete HelpWidget::getPasHelpNames();
    delete MannaSettings::getMannaSettings();
}

void MainWindow::newFile()
{
    m_editorTab->newFile();
}

void MainWindow::openFile()
{
    static QString dir;
    static QString selectedFilter = tr("All Files")+" (* *.*)";

    MannaSettings *settings = MannaSettings::getMannaSettings();
    settings->beginGroup("LastestOpenDir");
    dir = settings->value( "LODir",dir ).toString();

    //qDebug("************************");
    //qDebug(dir.toLatin1().constData());
    //qDebug(dir.left(dir.lastIndexOf("\\")+1).toLatin1().constData());
    //qDebug("************************");
    QString fn = QFileDialog::getOpenFileName(
                this,
                tr("Choose a file to open"),
#ifdef    Q_OS_WIN
                dir.left(dir.lastIndexOf("/")+1),
#else
                dir.left(dir.lastIndexOf("/")+1),
#endif
                tr("C/C++ Sources")+" (*.cpp *.c *.h);;"+
                tr("Pascal Sources")+" (*.pas *.pp);;"+
                tr("Texts")+" (*.txt *.TXT);;"+
                tr("All Files")+" (* *.*)",
                &selectedFilter);
    if (!fn.isEmpty()) {
        fn = QDir::fromNativeSeparators(fn);
        dir = QDir().absoluteFilePath(fn);
        settings->setValue("LODir", dir);
        settings->endGroup();
        doOpenFile(fn);
    } else {
        settings->setValue("LODir", dir);
        settings->endGroup();
    }
}

void MainWindow::slotOpenRecentFile()
{
    QAction *action = qobject_cast<QAction *>(sender());
    if (action) {
        QString fn = action->data().toString().remove("Recent|");
        doOpenFile(QDir::fromNativeSeparators(fn));
    }
}

bool MainWindow::save()
{
    if (m_editorTab->isCurrentNewFile()) {
        return saveAs();
    } else
        return
                m_editorTab->save();
}

bool MainWindow::saveAs()
{
    bool ret = m_editorTab->saveAs();
    if (ret) {
        QString fn;
        if (m_editorTab->currentFileName(fn)) {
            setRecentFile(fn);
        }
    }
    return ret;
}

void MainWindow::about()
{
    QMessageBox::about(this, tr("About %1").arg(PROGRAM_NAME),
        tr("<p style=\"text-align: center;\"><b>%1</b></p><br><br>"
           "<b>Version:</b>%2<br>"
           "<b>Author:</b>%3<br>"
           "<b>Home:</b><a href=\"%4\">%5</a><br>"
           "<p style=\"text-align: center;\">%6</p>").arg(PROGRAM_DESCRIPTION)
            .arg(PROGRAM_VERSION)
            .arg(PROGRAM_AUTHOR)
            .arg(PROGRAM_DOMAIN).arg(PROGRAM_DOMAIN)
            .arg(PROGRAM_COPYRIGHTS));
}

void MainWindow::installTranslators()
{
    m_myTranslator.load(":/translations/lang_zh_CN");
    m_qtTranslator.load(":/translations/qt_zh_CN");
    qApp->installTranslator(&m_myTranslator);
    qApp->installTranslator(&m_qtTranslator);
}

void MainWindow::createActions()
{
    actionNew->setShortcut(QKeySequence::New);
    actionNew->setStatusTip(tr("Create a new file"));
    connect(actionNew, SIGNAL(triggered()), this, SLOT(newFile()));

    actionOpen->setShortcut(QKeySequence::Open);
    actionOpen->setStatusTip(tr("Open an existing file"));
    connect(actionOpen, SIGNAL(triggered()), this, SLOT(openFile()));

    actionSave->setShortcut(QKeySequence::Save);
    actionSave->setStatusTip(tr("Save the document to disk"));
    connect(actionSave, SIGNAL(triggered()), this, SLOT(save()));

    actionSaveAs->setStatusTip(tr("Save the document under a new name"));
    connect(actionSaveAs, SIGNAL(triggered()), this, SLOT(saveAs()));

    actionCloseFile->setShortcut(QKeySequence::Close);
    actionCloseFile->setStatusTip(tr("Close current file"));
    connect(actionCloseFile, SIGNAL(triggered()),
        this, SLOT(slotCloseFile()));

    actionCloseAllFiles->setStatusTip(tr("Close all files"));
    connect(actionCloseAllFiles, SIGNAL(triggered()),
        this, SLOT(slotCloseAllFiles()));

    actionCloseOtherFiles->setStatusTip(tr("Close other files except current one"));
    connect(actionCloseOtherFiles, SIGNAL(triggered()),
        this, SLOT(slotCloseOtherFiles()));

    actionExit->setShortcut(QString("Ctrl+Q"));
    actionExit->setStatusTip(tr("Exit the application"));
    connect(actionExit, SIGNAL(triggered()), this, SLOT(close()));

    actionCut->setShortcut(QKeySequence::Cut);
    actionCut->setStatusTip(tr("Cut the current selection's contents to the "
                                "clipboard"));
    connect(actionCut, SIGNAL(triggered()), m_editorTab, SLOT(cut()));

    actionCopy->setShortcut(QKeySequence::Copy);
    actionCopy->setStatusTip(tr("Copy the current selection's contents to the "
    "clipboard"));
    connect(actionCopy, SIGNAL(triggered()), m_editorTab, SLOT(copy()));

    actionCut->setEnabled(false);
    actionCopy->setEnabled(false);
    connect(m_editorTab, SIGNAL(copyAvailable(bool)),
        actionCut, SLOT(setEnabled(bool)));
    connect(m_editorTab, SIGNAL(copyAvailable(bool)),
        actionCopy, SLOT(setEnabled(bool)));

    actionPaste->setShortcut(QKeySequence::Paste);
    actionPaste->setStatusTip(tr("Paste the clipboard's contents into the current "
                "selection"));
    connect(actionPaste, SIGNAL(triggered()), m_editorTab, SLOT(paste()));

    actionSelectAll->setShortcut(QKeySequence::SelectAll);
    actionSelectAll->setStatusTip(tr("Select all contents in current editor"));
    connect(actionSelectAll, SIGNAL(triggered()), m_editorTab, SLOT(selectAll()));

    actionUndo->setShortcut(QKeySequence::Undo);
    actionUndo->setStatusTip(tr("Undo last change"));
    connect(actionUndo, SIGNAL(triggered()), m_editorTab, SLOT(undo()));

    actionRedo->setShortcut(QKeySequence::Redo);
    actionRedo->setStatusTip(tr("Redo last canceled change"));
    connect(actionRedo, SIGNAL(triggered()), m_editorTab, SLOT(redo()));

    actionSearch->setShortcut(QKeySequence::Find);
    actionSearch->setStatusTip(tr("Search in the file"));
    connect(actionSearch, SIGNAL(triggered()), this, SLOT(slotSearch()));

    //actionSearchNext->setShortcut(QKeySequence::FindNext);
    actionSearchNext->setShortcut(QString("F3"));
    actionSearchNext->setStatusTip(tr("Search next result"));
    connect(actionSearchNext, SIGNAL(triggered()), this, SLOT(slotSearchNext()));

    actionSearchPrevious->setShortcut(QKeySequence::FindPrevious);
    actionSearchPrevious->setStatusTip(tr("Search previous result"));
    connect(actionSearchPrevious, SIGNAL(triggered()), this, SLOT(slotSearchPrevious()));

    actionGoto->setShortcut(QString("Ctrl+G"));
    actionGoto->setStatusTip(tr("Go to line in the file"));
    connect(actionGoto, SIGNAL(triggered()), this, SLOT(slotGoto()));

    actionGotoBrace->setShortcut(QString("Ctrl+]"));
    actionGotoBrace->setStatusTip(tr("Go to the position of the corresponding brace."));
    connect(actionGotoBrace,SIGNAL(triggered()),this,SLOT(slotGotoBrace()));

    actionBreakpoint->setShortcut(QString("F9"));
    actionBreakpoint->setStatusTip(tr("Toggle breakpoint"));
    connect (actionBreakpoint, SIGNAL(triggered()), this, SLOT(slotToggleBreakpoint()));

    actionBreakpointsManager->setShortcut(QString("Ctrl+F9"));
    actionBreakpointsManager->setStatusTip(tr("Manage all breakpoints"));
    connect (actionBreakpointsManager, SIGNAL(triggered()), this, SLOT(slotManageBreakpoints()));

    actionSettings->setStatusTip(tr("Settings"));
    connect (actionSettings, SIGNAL(triggered()), this, SLOT(slotSettings()));

    actionReset_extern_tool->setStatusTip(tr("Reset extern tools"));
    connect (actionReset_extern_tool, SIGNAL(triggered()), this, SLOT(resetExternTool()));

    actionCompile->setShortcut(QString("F7"));
    actionCompile->setStatusTip(tr("Compile current source."));
    connect (actionCompile, SIGNAL(triggered()),
            this, SLOT(slotCompile()));

    actionStopCompile->setShortcut(QString("Ctrl+F7"));
    actionStopCompile->setStatusTip(tr("Stop current compiling process."));
    connect (actionStopCompile, SIGNAL(triggered()),
            this, SLOT(slotStopCompile()));
    actionStopCompile->setEnabled(false);

    actionExecute->setShortcut(QString("Ctrl+F5"));
    actionExecute->setStatusTip(tr("Run current executable."));
    connect (actionExecute, SIGNAL(triggered()),
            this, SLOT(slotExecute()));

    actionStopExecute->setStatusTip(tr("Stop current running target"));
    connect (actionStopExecute, SIGNAL(triggered()),
            this, SLOT(slotStopExecute()));
    actionStopExecute->setEnabled(false);
#ifdef Q_OS_WIN
    actionStopExecute->setVisible(false);
#endif
    actionDebug->setText(tr("Start"));
    actionDebug->setShortcut(QString("F5"));
    actionDebug->setStatusTip(tr("Debug current executable."));
    connect (actionDebug, SIGNAL(triggered()), this, SLOT(slotDebug()));

    actionStopDebug->setText(tr("Stop"));
    actionStopDebug->setShortcut(QString("Shift+F5"));
    actionStopDebug->setStatusTip(tr("Stop debug"));
    connect (actionStopDebug, SIGNAL (triggered ()), this, SLOT (stopDebug ()));

    actionParams->setText(tr("File Option"));
    actionParams->setStatusTip(tr("Set file option"));
    connect (actionParams, SIGNAL(triggered()), this, SLOT(slotSetParams()));

    actionPauseResume->setText(tr("Pause"));
    //actionStopDebug->setShortcut(tr("Shift+F5"));
    actionPauseResume->setStatusTip(tr("Pause debug"));
    //connect (actionPauseResume, SIGNAL (triggered ()), this, SLOT (slotPauseResume ()));
    //connect (this,SIGNAL(pauseDebug()),this,SLOT(slotOnPause()));
        connect (actionPauseResume, SIGNAL (triggered ()), this, SLOT (slotOnPause ()));
    //connect (this,SIGNAL(continueDebug()),this,SLOT(slotOnContinue()));

    actionStepOver->setShortcut(QString("F10"));
    actionStepOver->setStatusTip(tr("Step Over"));
    connect (actionStepOver, SIGNAL(triggered()), this, SLOT(slotStepOver()));

    actionRuntoCursor->setShortcut(QString("Ctrl+F10"));
    actionRuntoCursor->setStatusTip(tr("Run to cursor"));
    connect (actionRuntoCursor, SIGNAL(triggered()), this, SLOT(slotRuntoCursor()));

    actionStepInto->setShortcut(QString("F11"));
    actionStepInto->setStatusTip(tr("Step Into"));
    connect (actionStepInto, SIGNAL(triggered()), this, SLOT(slotStepInto()));

    actionStepOut->setShortcut(QString("Shift+F11"));
    actionStepOut->setStatusTip(tr("Step Out"));
    connect (actionStepOut, SIGNAL(triggered()), this, SLOT(slotStepOut()));

    actionAbout->setStatusTip(tr("Show the application's About box"));
    connect(actionAbout, SIGNAL(triggered()), this, SLOT(about()));

    //actionHelp->setShortcut(tr("F1"));
    actionHelp->setStatusTip(tr("Help"));
    connect(actionHelp, SIGNAL(triggered()), this, SLOT(slotHelp()));

    actionChinese->setStatusTip(tr("Chinese"));
    connect(actionChinese,SIGNAL(triggered()),this,SLOT(slotLanguageChinese()));

    actionEnglish->setStatusTip(tr("English"));
    connect(actionEnglish,SIGNAL(triggered()),this,SLOT(slotLanguageEnglish()));
}

void MainWindow::reCreateStatusTips() {

    actionNew->setStatusTip(tr("Create a new file"));
    actionOpen->setStatusTip(tr("Open an existing file"));
    actionSave->setStatusTip(tr("Save the document to disk"));
    actionSaveAs->setStatusTip(tr("Save the document under a new name"));
    actionCloseFile->setStatusTip(tr("Close current file"));
    actionCloseAllFiles->setStatusTip(tr("Close all files"));
    actionCloseOtherFiles->setStatusTip(tr("Close other files except current one"));
    actionExit->setStatusTip(tr("Exit the application"));
    actionCut->setStatusTip(tr("Cut the current selection's contents to the "
                                "clipboard"));
    actionCopy->setStatusTip(tr("Copy the current selection's contents to the "
    "clipboard"));
    actionPaste->setStatusTip(tr("Paste the clipboard's contents into the current "
                "selection"));
    actionSelectAll->setStatusTip(tr("Select all contents in current editor"));
    actionUndo->setStatusTip(tr("Undo last change"));
    actionRedo->setStatusTip(tr("Redo last canceled change"));
    actionSearch->setStatusTip(tr("Search in the file"));
    actionSearchNext->setStatusTip(tr("Search next result"));
    actionSearchPrevious->setStatusTip(tr("Search previous result"));
    actionGoto->setStatusTip(tr("Go to line in the file"));
    actionGotoBrace->setStatusTip(tr("Go to the position of the corresponding brace."));
    actionBreakpoint->setStatusTip(tr("Toggle breakpoint"));
    actionSettings->setStatusTip(tr("Settings"));
    actionReset_extern_tool->setStatusTip(tr("Reset extern tools"));
    actionCompile->setStatusTip(tr("Compile current source."));
    actionStopCompile->setStatusTip(tr("Stop current compiling process."));
    actionExecute->setStatusTip(tr("Run current executable."));
    actionStopExecute->setStatusTip(tr("Stop current running target"));
    actionDebug->setText(tr("Start"));
    actionDebug->setStatusTip(tr("Debug current executable."));
    actionStopDebug->setStatusTip(tr("Stop debug"));
    actionPauseResume->setText(tr("Pause"));
    //actionStopDebug->setShortcut(tr("Shift+F5"));
    actionPauseResume->setStatusTip(tr("Pause debug"));
    //connect (this,SIGNAL(continueDebug()),this,SLOT(slotOnContinue()));
    actionStepOver->setStatusTip(tr("Step Over"));
    actionRuntoCursor->setStatusTip(tr("Run to cursor"));
    actionStepInto->setStatusTip(tr("Step Into"));
    actionStepOut->setStatusTip(tr("Step Out"));
    actionAbout->setStatusTip(tr("Show the application's About box"));
    actionHelp->setStatusTip(tr("Help"));
    actionChinese->setStatusTip(tr("Chinese"));
    actionEnglish->setStatusTip(tr("English"));
}

void MainWindow::createMenus()
{
//    addDockWidget(Qt::RightDockWidgetArea, dockRegisters);
//    tabifyDockWidget(dockRegisters, dockCallStack);
//    splitDockWidget(dockRegisters, dockCallStack, Qt::Vertical);
    tabifyDockWidget(dockOutputs, gdbOutputDock);
    tabifyDockWidget(gdbOutputDock, callStackDock);
    tabifyDockWidget(callStackDock, treeLocalDock);
    tabifyDockWidget(treeLocalDock, treeWatchDock);
    tabifyDockWidget(treeWatchDock, memoryDock);
    dockOutputs->raise();
    menu_View->addSeparator();
    menu_View->addAction(fileBrowserDock->toggleViewAction());
    menu_View->addAction(dockOutputs->toggleViewAction());
    menu_View->addAction(gdbOutputDock->toggleViewAction());
    menu_View->addAction(callStackDock->toggleViewAction());
    menu_View->addAction(treeLocalDock->toggleViewAction());
    menu_View->addAction(treeWatchDock->toggleViewAction());
    menu_View->addAction(memoryDock->toggleViewAction());
//    menu_View->addAction(dockCallStack->toggleViewAction());
//    menu_View->addAction(dockRegisters->toggleViewAction());
    menu_View->addSeparator();
//    dockCallStack->setVisible(false);
//    dockRegisters->setVisible(false);
//    m_fileBrowser->setVisible(true);
}

void MainWindow::createToolBars()
{
}

void MainWindow::createStatusBar()
{
    statusBar()->showMessage(tr("Ready"));
}

void MainWindow::readSettings()
{
    MannaSettings *settings = MannaSettings::getMannaSettings();
    QPoint pos = settings->value("pos", QPoint(200, 200)).toPoint();
    QSize size = settings->value("size", QSize(400, 400)).toSize();
    resize(size);
    move(pos);
}

void MainWindow::loadRecentFiles()
{
    MannaSettings *settings = MannaSettings::getMannaSettings();

    settings->beginGroup("RecentFiles");
    QStringList files = settings->value("RecentFilesList").toStringList();

    QStringList existingFiles;
    foreach (QString fileName, files) {
        if (QFile(fileName).exists())
            existingFiles.push_back(fileName);
    }
    if (existingFiles.size() < files.size()) {
        settings->setValue("RecentFilesList", files);
        files = existingFiles;
    }

    int numRecentFiles = qMin(files.size(), (int)maxRecentsFiles);

    for (int i = 0; i < numRecentFiles; ++i) {
        QString text = tr("&%1 %2").arg(i + 1).arg(strippedName(files[i]));
        m_actionsRecentsFiles[i]->setText(text);
        m_actionsRecentsFiles[i]->setData("Recent|"+files[i]);
        m_actionsRecentsFiles[i]->setVisible(true);
    }
    for (int j = numRecentFiles; j < maxRecentsFiles; ++j) {
        m_actionsRecentsFiles[j]->setVisible(false);
    }
    settings->endGroup();
}

void MainWindow::setRecentFile(const QString &file)
{
    MannaSettings *settings = MannaSettings::getMannaSettings();

    settings->beginGroup("RecentFiles");
    QStringList files = settings->value("RecentFilesList").toStringList();
    files.removeAll(file);
    files.prepend(file);
    while (files.size() > maxRecentsFiles)
        files.removeLast();

    settings->setValue("RecentFilesList", files);
    settings->endGroup();

    loadRecentFiles();
}

void MainWindow::writeSettings()
{
    MannaSettings *settings = MannaSettings::getMannaSettings();
    settings->setValue("pos", pos());
    settings->setValue("size", size());

    settings->beginGroup("OpenedFileList");
    QStringList files = settings->value("OpenedFiles").toStringList();

    while (files.count() > 0) {
        files.removeLast();
    }

    for (int i = 0;i < m_editorTab->count();++i) {
        MEditor *e = m_editorTab->editor(i);
        files.append(e->getFileName());
        //qDebug(editor->getFileName().toLatin1().constData());
    }

    settings->setValue("OpenedFiles", files);

    QString file;
    m_editorTab->currentFileName(file);
    settings->setValue("LastOpenedFile", file);
    settings->endGroup();
}

void MainWindow::slotFileBrowserDblClickFile(QString fn)
{
    doOpenFile(QDir::fromNativeSeparators(fn));
}

bool MainWindow::maybeSave()
{
    if (m_editorTab->hasFileModified()) {
        int ret = QMessageBox::warning(this, PROGRAM_NAME,
            tr("The document has been modified.\n"
            "Do you want to save your changes?"),
            QMessageBox::Yes | QMessageBox::Default,
            QMessageBox::No,
            QMessageBox::Cancel | QMessageBox::Escape);
        if (ret == QMessageBox::Yes)
            return m_editorTab->saveAll();
        else if (ret == QMessageBox::Cancel)
            return false;
    }
    return true;
}

QString MainWindow::strippedName(const QString &fullFileName)
{
    //return QFileInfo(fullFileName).fileName();
    return QFileInfo(fullFileName).absoluteFilePath();
}

void MainWindow::connectSignals()
{
    /* connect to editor tabwidget's signals. */
    connect (m_editorTab, SIGNAL(fileClosed(int)),
        this, SLOT(slotFileClosed(int)));

    connect (buildLogs, SIGNAL(buildLogClicked(QString, int)),
        this, SLOT(slotBuildLogClicked(QString, int)));

    connect(addWatch, SIGNAL(clicked()), this, SLOT(slotAddWatch()) );
    connect(removeWatch, SIGNAL(clicked()), this, SLOT(slotRemoveWatch()) );

    connect (m_fileBrowser, SIGNAL(fileDblClicked(QString)),
        this, SLOT(slotFileBrowserDblClickFile(QString)));

    connect (m_finder, SIGNAL(findRequest(QString, bool, bool, bool, bool)),
        this, SLOT(slotFindRequest(QString, bool, bool, bool, bool)));


    connect (m_finder, SIGNAL(replaceRequest(QString,QString,bool,bool,bool,bool)),
        this,SLOT(slotReplaceRequest(QString,QString,bool,bool,bool,bool)));

    connect (addrLine, SIGNAL(returnPressed()), memBtn, SLOT(click()));
    connect (bytesLine, SIGNAL(returnPressed()), memBtn, SLOT(click()));
    connect (memBtn, SIGNAL(clicked()), this, SLOT(slotShowMemory()));
}

void MainWindow::slotFileClosed(int /*index*/)
{
    MannaSettings *settings = MannaSettings::getMannaSettings();
    settings->beginGroup("OpenedFileList");
    QStringList files = settings->value("OpenedFiles").toStringList();

    while (files.count() > 0) {
        files.removeLast();
    }

    for (int i = 0;i < m_editorTab->count();++i) {
        MEditor * e = m_editorTab->editor(i);
        files.append(e->getFileName());
        //qDebug(editor->getFileName().toLatin1().constData());
    }

    settings->setValue("OpenedFiles", files);
    settings->endGroup();

    //index = 0;
}

void MainWindow::slotCloseFile()
{
    m_editorTab->closeCurrentTab();
}

void MainWindow::slotCloseAllFiles()
{
    m_editorTab->closeAllTabs();
}

void MainWindow::slotCloseOtherFiles()
{
    m_editorTab->closeOtherTabs();
}

void MainWindow::slotCompile()
{
    doCompile(false, false);
}

void MainWindow::doCompile(bool run, bool debug)
{
    QString fullname;
    if (!m_editorTab->currentFileName(fullname))
        return;
    if (fullname.isEmpty() && m_editorTab->isCurrentModified()) {
        int ret = QMessageBox::warning(this, PROGRAM_NAME,
                    tr("The source has no name and been modified.\n"
                    "Do you want to save your changes?"),
                    QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
                    QMessageBox::Yes);
        if (ret == QMessageBox::Cancel)
            return;
        else if (ret == QMessageBox::No) {
            return;
        }
        saveAs();
    }
    if (m_editorTab->isCurrentModified()) {
        /*
        int ret = QMessageBox::warning(this, PROGRAM_NAME,
                    tr("The source has been modified.\n"
                    "Do you want to save your changes?"),
                    QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
                    QMessageBox::Yes);
        if (ret == QMessageBox::Cancel)
            return;
        else if (ret == QMessageBox::No) {
            return;
        }*/
        save();
    }

    QString filename, dirname, exename;
    if (!getCurrentFileNames(fullname, dirname, filename, exename)) {
        /* FIXME: Still can not get these names? */
        return;
    }
    QString cmdline;
    SourceType type;
    if (!getSourceType(type, filename)) {
        QMessageBox::warning(this, PROGRAM_NAME,
                    tr("This file can not be compiled!\n"),
                    QMessageBox::Ok);
        return;
    }

    if (!getCompileCmd(cmdline, filename, exename)) {
        return;
    }

    QString compileOpt = m_editorTab->getCurrentCompileOption();
    cmdline = cmdline + " " + compileOpt;
    qDebug() << cmdline;
    /* Begin to build. */
    buildLogs->clear();
    //messageTabWidget->setCurrentWidget(buildLogTab);
    dockOutputs->raise();
    Build *builder = new Build(this, dirname, fullname, cmdline, type);

    connect(builder, SIGNAL(buildFinished(bool)), this, SLOT(slotEndBuild(bool)) );
    connect(builder, SIGNAL(message(QString, QString, SourceType)), buildLogs, SLOT(slotMessagesBuild(QString, QString, SourceType)) );
    /* count up warnings and errors */
    connect(buildLogs, SIGNAL(incErrors()), builder, SLOT(slotIncErrors()) );
    connect(buildLogs, SIGNAL(incWarnings()), builder, SLOT(slotIncWarnings()) );

    /* Disconnect previous connected slots to avoid multiple connection.
     * connect does not check the duplicated connections.
     */
    disconnect (this, SIGNAL(buildFinished(bool, QString)),
        this, SLOT(slotRunAfterBuild(bool, QString)));
    disconnect (this, SIGNAL(buildFinished(bool, QString)),
        this, SLOT(slotDebugAfterBuild(bool, QString)));

    if (run) {
        connect (this, SIGNAL(buildFinished(bool, QString)),
            this, SLOT(slotRunAfterBuild(bool, QString)));
    }
    if (debug) {
        connect (this, SIGNAL(buildFinished(bool, QString)),
            this, SLOT(slotDebugAfterBuild(bool, QString)));
    }

    changeRunState (CompileMode);
    builder->start();
}

void MainWindow::slotStopCompile()
{
    emit stopBuild();
}

void MainWindow::slotExecute()
{
    QString fullname, filename, dirname, exename;

    if (!getCurrentFileNames(fullname, dirname, filename, exename))
        return;

    if (m_editorTab->isCurrentModified()) {
        int ret = QMessageBox::warning(this, PROGRAM_NAME,
                    tr("The source has been modified.\n"
                    "Do you want to save your changes and compile the source?"),
                    QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
                    QMessageBox::Yes);
        if (ret == QMessageBox::Cancel)
            return;
        else if (ret == QMessageBox::No) {
            /* Nothing to do? */
            ;
        } else {
            save();
            doCompile(true);
            return;
        }
    }

    if (compareExecutalbAndSource(dirname, filename, exename) >= 0) {
        /* executable file is not update. */
        doCompile(true);
    } else
        doExecute(fullname);
}

void MainWindow::slotStopExecute()
{
    //emit stopExecute();
    //if (runProcess->state() != QProcess::NotRunning) {
    runProcess->terminate();
    if (!runProcess->waitForFinished(1000)) {
        runProcess->kill();
    }
    //}
    changeRunState(EditMode);
}

void MainWindow::slotStopExecute(QProcess::ProcessState newstate)
{
    //emit stopExecute();
    //qDebug(QString("--%1").arg(newstate).toLatin1().constData());
    if (newstate == QProcess::NotRunning) {
        changeRunState(EditMode);
    }
}

void MainWindow::slotEndBuild(bool success)
{
    QString msg;
    Build* builder = (Build *)sender();
    if (success) {
        msg = tr("Build finished successfully.");
    } else {
        msg = tr("Build finished with")+" ";
        if ( builder->nbErrors() )
            msg += QString::number(builder->nbErrors())+" "+tr("error(s)")+ (builder->nbWarnings() ? " "+tr("and")+ " " : QString(" "));
        if ( builder->nbWarnings() )
            msg += QString::number(builder->nbWarnings())+" "+tr("warning(s)")+" ";
    }
    buildLogs->slotMessagesBuild( QString("\n"+msg+"\n"), "");


    changeRunState(EditMode);

    emit buildFinished(success, builder->srcFileName());
}

void MainWindow::slotBuildLogClicked(QString fn, int line)
{
    if (!fn.isEmpty()) {
        if (doOpenFile(QDir::fromNativeSeparators(fn))) {
            m_editorTab->gotoLine(line, true, true);
            m_editorTab->currentWidget()->setFocus();
        }
    }
}

void MainWindow::slotRunAfterBuild(bool succ, QString srcfile)
{
    if (succ)
        doExecute(srcfile);
    else {
        QMessageBox::warning(this, PROGRAM_NAME,
                    tr("Compile failed!\n"
                    "Can not execute the target!"),
                    QMessageBox::Ok);
    }
}

void MainWindow::doExecute(QString srcfile)
{
    /* We can not use getCurrentFileNames method, coz
     * user may change the current file.
     */
    QFileInfo fi(srcfile);
    QString dirname = fi.absoluteDir().absolutePath();
    QString targetname = m_srcExeMap.value(srcfile);

    QStringList env = QProcess::systemEnvironment();
    QString exename = dirname + '/' + targetname;

#ifdef Q_OS_WIN
    QString bat = QDir::toNativeSeparators(m_curDirectory + "/exe.bat");
    QStringList aidExename = exename.split('/');
    QString targetExename;
    targetExename = aidExename[0];
    for (int i = 1;i < aidExename.size();++i) {
        targetExename += QString("\\\"%1\"").arg(aidExename[i]);
        //targetExename = QString("\"%1\"").arg(aidExename[i]);
    }
    FILE * debug_file = fopen(bat.toLocal8Bit().constData (),"w");
    QString execOption = m_editorTab->getExecOption(srcfile);
    if (debug_file) {
        fprintf(debug_file,"@echo off\n");
        //fprintf(debug_file,"cd \"%s\"\n",dirname.replace("/","\\").toAscii().constData());
        //fprintf(debug_file,"%s\n",targetExename.toAscii().constData());
        fprintf(debug_file,"%s %s\n",targetExename.toLocal8Bit().constData(), execOption.toLocal8Bit().constData());
        fprintf(debug_file,"pause");
    } else {
        //qDebug("can't open the .bat file!");
    }
    fclose(debug_file);

    runProcess = new QProcess;
    runProcess->setWorkingDirectory(dirname);
    //qDebug(dirname.toLatin1().constData());
    bat = QString("\"%1\"").arg(bat.toLocal8Bit ().constData ());
    //connect(runProcess,SIGNAL(stateChanged(QProcess::ProcessState)),this,SLOT(slotStopExecute(QProcess::ProcessState)));
    qint64 aid;
    QStringList args;
    runProcess->startDetached(bat.toLocal8Bit().constData (),args,dirname,&aid);

#else
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));

    //QString sh_name = m_curDirectory + "/exe.sh";
    QString sh_name = "/tmp/exe.sh";

    QStringList aidShname = exename.split('/');
    exename = aidShname[0];
    for (int i = 1;i < aidShname.size();++i) {
        exename += QString("/\"%1\"").arg(aidShname[i]);
    }
    //qDebug(sh_name.toLatin1().constData());
    FILE *debug_sh = fopen(sh_name.toLocal8Bit().constData(),"w");
    QString execOption = m_editorTab->getExecOption(srcfile);
    if (debug_sh) {
        fprintf(debug_sh,"#!/bin/bash\n");
        fprintf(debug_sh,"%s %s\n",exename.toLocal8Bit().constData(), execOption.toLocal8Bit().constData());
        fprintf(debug_sh,"read\n");
        fprintf(debug_sh,"exit 0");
    }
    fclose(debug_sh);
    chmod(sh_name.toLocal8Bit().constData(),S_IRUSR|S_IWUSR|S_IXUSR);
    //sh_name = QString("\"%1/exe.sh\"").arg(m_curDirectory);
    //qDebug(sh_name.toLatin1().constData());
    //QProcess *runProcess;
    QString cmd = "xterm -fn -misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso10646-1 ";
    cmd = cmd + sh_name;
    //qDebug(cmd.toLatin1().constData());
    runProcess = new QProcess;
    runProcess->setWorkingDirectory(dirname);
    connect(runProcess,SIGNAL(stateChanged(QProcess::ProcessState)),this,SLOT(slotStopExecute(QProcess::ProcessState)));
    runProcess->start(cmd);
    changeRunState(ExecMode);
#endif
}

/* return 2, exec file does not exist.
 * return 1, src file is newer than exe file.
 * return 0, src file is at same time with exe file.
 * return -1, src file is older than exe file.
 */
int MainWindow::compareExecutalbAndSource(QString dirname, QString srcname, QString exename)
{
    QFileInfo src(dirname + "/" + srcname);
    QFileInfo exe(dirname + "/" + exename);

    if (!exe.exists())
        return 2;

    QDateTime dtSrc = src.lastModified();
    QDateTime dtExe = exe.lastModified();

    if (dtSrc > dtExe)
        return 1;
    else if (dtSrc < dtExe)
        return -1;
    else
        return 0;
}

void MainWindow::slotExecuteOutput(QString msg, bool bStdErr)
{
    appendToExecuteOutput(msg, bStdErr);
}

void MainWindow::slotExecuteFinished(bool started, int exitCode, QProcess::ExitStatus exitStatus)
{
    if (started) {
        if (exitStatus == QProcess::NormalExit) {
            QMessageBox::information(this, PROGRAM_NAME,
                tr("The program exit with code %1 normally.").arg(exitCode));
        } else {
            QMessageBox::information(this, PROGRAM_NAME,
                tr("The program has crashed."));
        }
    } else {
        QMessageBox::information(this, PROGRAM_NAME,
            tr("The program can not start!"));
    }
    changeRunState(EditMode);
}

void MainWindow::appendToExecuteOutput(QString list, bool /*Stderr*/)
{
    list = "";
    //Stderr = false;
//#if 1
//    QString newlines, lines;
//    int cnt;
//    newlines = list.section('\n', -TARGET_OUTPUT_LIMIT);
//    cnt = newlines.count("\n");
//    if ( cnt == 0)
//        return;
//
//    lines = (m_targetOutput + newlines).section('\n', -TARGET_OUTPUT_LIMIT);
//    execOutput->clear();
//    lines.remove ("\r");
//    execOutput->append(lines);
//    m_targetOutput = lines;
//#endif
}

void MainWindow::slotDebug()
{
    /* We can not use getCurrentFileNames method, coz
     * user may change the current file.
     */
    TRACEFUNC(slotDebug);
    if (m_state == DebugMode)
    {
        if (! userPrompt ()) {
            m_execClient->resume ();
            actionPauseResume->setEnabled(true);
            //在调试过程暂停于某一行之其它调试按钮会是不可用的,以避免不必要的输入导致程序失    setButtonState(0);
        }
        return;
    }

    QString fullname, dirname, srcname, exename;
    if (!getCurrentFileNames(fullname, dirname, srcname, exename)) {
        return;
    }
    //qDebug(fullname.toLatin1().constData());
    if (m_editorTab->isCurrentModified()) {

        int ret = QMessageBox::warning(this, PROGRAM_NAME,
                    tr("The source has been modified.\n"
                    "Do you want to save your changes and compile the source?"),
                    QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
                    QMessageBox::Yes);
        if (ret == QMessageBox::Cancel)
            return;
        else if (ret == QMessageBox::No) {
            /* Nothing to do? */
            ;
        } else {
            save();
            doCompile(false, true);
            return;
        }
    }

    if (compareExecutalbAndSource(dirname, srcname, exename) >= 0) {
        /* executable file is not update. */
        doCompile(false, true);
    } else {
        //getVarList(dirname+"/"+exename);
        doDebug(fullname);
    }
}

void MainWindow::slotPauseResume()
{
/*
if ( actionPauseResume->text() == tr("Pause") ) {
 #ifdef Q_OS_LINUX
         emit pauseDebug();
 #else
         logDebug->append(tr("Pause is impossible under Windows. Use breakpoints."));
         QMessageBox::information(this, PROGRAM_NAME,
                 tr("Pause is impossible under Windows. Use breakpoints."));
 #endif
     } else {
         //emit continueDebug();
    }*/
}

void MainWindow::slotToggleBreakpoint(QString c)
{
    MEditor *e = m_editorTab->currentEditor();
    if (!e) return;

    int l;
    bool set = e->toggleBreakpoint(l, true, c);

    QString f = e->getFileName();
    QFileInfo fi(f);
    QString fn = fi.fileName();

    m_execClient->setBreakpoint (fn, l, set, c);
}

void MainWindow::slotToggleBreakpoint(QString f, int l)
{
    MEditor *e = m_editorTab->editor(f);
    if (!e) return;
    QFileInfo fi(f);
    m_execClient->setBreakpoint(fi.fileName(), l, e->toggleBreakpoint(l));
}

void MainWindow::toConditional(QString f, int l, QString c)
{
    MEditor *e = m_editorTab->editor(f);
    e->toggleBreakpoint(l);
    e->toggleBreakpoint(l, false, c);
    m_execClient->setBreakpoint(f, l, true, c, true);
}

void MainWindow::slotStepOver()
{
    if (m_state == EditMode) {
        stopAtMain = true;
        slotDebug();
    } else {
        if (! userPrompt ())
            m_execClient->stepOver ();
            //只有在调试运行的过程遇到断点之前,此功能是可用
            actionPauseResume->setEnabled(true);
            //在调试过程暂停于某一行之其它调试按钮会是不可用的,以避免不必要的输入导致程序失
    }
}

void MainWindow::slotRuntoCursor() {
    if (! userPrompt()) {
        QString fileName;
        if (m_editorTab->currentFileName(fileName)) {
            MEditor * editor = m_editorTab->editor (fileName, true);
            QPoint cur = editor->cursorPosition();
            ////qDebug(QString("line->%1").arg(fileName).toLatin1().constData());
            QMap<int, QString> map;
            editor->getAllBreakpoints(map);
            foreach(int i,map.keys()) {
                if (i == cur.y()+1) {
                    m_execClient->resume();
                    return;
                }
            }
            m_execClient->runtoCursor(fileName,cur.y()+1);
            actionPauseResume->setEnabled(true);
            setButtonState(0);
        }
    }
}

void MainWindow::slotStepInto()
{
    if (! userPrompt ()) {
        m_execClient->stepInto ();
        actionPauseResume->setEnabled(true);
        setButtonState(0);
    }

}

void MainWindow::slotStepOut()
{
    if (! userPrompt ()) {
        m_execClient->stepOut ();
        actionPauseResume->setEnabled(true);
        setButtonState(0);
    }
}

void MainWindow::slotDebugAfterBuild(bool succ, QString srcfile)
{
    if (succ) {
        QString fullname, dirname, srcname, exename;
        if (!getCurrentFileNames(fullname, dirname, srcname, exename)) {
            return;
        }
        //getVarList(dirname+"/"+exename);
        doDebug(srcfile);
    } else {
        QMessageBox::warning(this, PROGRAM_NAME,
                    tr("Compile failed!\n"
                    "Can not debug the target!"),
                    QMessageBox::Ok);
    }
}

void MainWindow::doDebug(QString srcfile)
{
    TRACEFUNC(doDebug);
    /* We can not use getCurrentFileNames method, coz
     * user may change the current file.
     */
    QFileInfo finfo(srcfile);
    QString filename = finfo.fileName();
    QString dirname = finfo.absoluteDir().absolutePath();

    QString targetname = m_srcExeMap.value(srcfile);

    QString exename = dirname + "/" + targetname;

    SourceType type;
    if (!getSourceType(type, filename)) {
        QMessageBox::warning(this, PROGRAM_NAME,
            tr("The document can not be debugged."),
            QMessageBox::Ok);
        return;
    }

    if (filename.endsWith(".pas", Qt::CaseInsensitive)) {
        m_variableClient->setIsPascal(true);
    } else {
        m_variableClient->setIsPascal(false);
    }

    //qDebug(srcfile.toLatin1().constData());
    MEditor *editor = m_editorTab->editor (srcfile, true);

    if (! editor)
    {
        QMessageBox::critical (this, PROGRAM_NAME,
            QString ("Can NOT open document %1").arg (srcfile),
            QMessageBox::Ok);
        return;
    }

    m_activeFileName = srcfile;
    m_activeFileName = QDir::fromNativeSeparators(m_activeFileName);
    m_lastModified = editor->lastModified ();

    logDebug->clear();

    if (! m_defaultClient->startDebug (dirname, exename))
    {
        QMessageBox::critical (this, PROGRAM_NAME,
            QString (tr("Can not launch gdb!")),
            QMessageBox::Ok);
        return;
    }

    initCurrentBreakpoints ();

    m_execClient->run (stopAtMain, m_editorTab->getExecOption(srcfile));

    actionDebug->setText (tr ("Continue"));

    gdbOutputDock->raise();
    changeRunState(DebugMode);

    actionPauseResume->setEnabled(true);
}

void MainWindow::stopDebug()
{
    m_execClient->stop ();
    stopAtMain = false;
}

void MainWindow::slotSetParams()
{
    m_editorTab->slotSetFileOption(true);
}

void MainWindow::slotOnPause()
{
    //actionPauseResume->setIcon( QIcon(":/images/debug/resume.png") );
    //actionPauseResume->setToolTip( tr("Continue") );
    //actionPauseResume->setText( tr("Continue") );
#ifdef Q_OS_LINUX
    qDebug("slotOnPause");
    actionPauseResume->setEnabled(false);
    m_execClient->pause();
#else
    logDebug->append(tr("Pause is impossible under Windows. Use breakpoints."));
    QMessageBox::information(this, PROGRAM_NAME,
                 tr("Pause is impossible under Windows. Use breakpoints."));
#endif
}

void MainWindow::slotOnContinue()
{
    /*actionPauseResume->setIcon( QIcon(":/images/debug/dbgpause.png") );
    actionPauseResume->setText( tr("Pause") );
    actionPauseResume->setToolTip( tr("Pause") );
    m_execClient->resume ();*/
}

void MainWindow::slotDebugFinished()
{
    actionDebug->setText(tr("Start"));

    MEditor *editor = m_editorTab->editor (m_activeFileName);
    if (editor)
        editor->setStepMarker ();
    m_activeFileName.clear ();

    changeRunState(EditMode);
    //m_editorTab->setAllTabsReadOnly(false);
}

void MainWindow::setDebugMessage (QString message, int level)
{
    //qDebug (message.toLatin1 ());

    if (level == GDBMI::NORMAL)
        logDebug->append (
            QString ("<font color=\"black\">%1</font>").arg (message));
    else {
        logDebug->append (
            QString ("<font color=\"red\">%1</font>").arg (message));
        if (message.contains("Segmentation fault")) {
            QMessageBox::warning (this, PROGRAM_NAME,tr("An segment error occured!Please stop the debug process and check your source code."),QMessageBox::Ok,QMessageBox::Cancel);
        }
    }

    if (message.contains("no line number") || level != GDBMI::NORMAL) {
        MEditor * editor = m_editorTab->editor (m_activeFileName, true);
        if (editor)
        {
            m_editorTab->setCurrentWidget (editor);
            editor->setStepMarker (lastStepLine);
            qDebug("stop at line :%d\n",lastStepLine);
        }
    }
}

void MainWindow::slotaddVarWatch(QString var) {
    qDebug() << "m_variableClient";
    if (! m_variableClient->addWatch (var)) {
        QMessageBox::warning (0, PROGRAM_NAME,
            tr ("The variable \"%1\"\n already exists.").arg (var),
            tr ("Cancel"));
    }

    //messageTabWidget->setCurrentWidget(debugWatchTab);
    treeWatchDock->raise();
    return;
}

void MainWindow::slotAddWatch(QString str /*=""*/)
{
    bool ok;
    QString var = QInputDialog::getText(this, PROGRAM_NAME,
                    tr("New Watch:"), QLineEdit::Normal,    str, &ok);
    if (!ok || var.isEmpty())
        return;

    if (! m_variableClient->addWatch (var))
        QMessageBox::warning (0, PROGRAM_NAME,
            tr ("The variable \"%1\"\n already exists.").arg (var),
            tr ("Cancel"));
}

void MainWindow::slotRemoveWatch()
{
    QList<QTreeWidgetItem *> sels = treeWatchWidget->selectedItems ();

    if (! sels.empty () && sels.front ()->parent () == 0)
    {
        // user select a top level item
        m_variableClient->delWatch (
            treeWatchWidget->indexOfTopLevelItem (sels.front ()));
    }
 }

void MainWindow::initCurrentBreakpoints()
{
    MEditor *e = m_editorTab->currentEditor();
    if (!e) return;

    QFileInfo fi(e->getFileName());
    QString fn = fi.fileName();

    QMap<int, QString> map;
    e->getAllBreakpoints(map);

    for (QMap<int, QString>::iterator i = map.begin(); i != map.end(); ++i) {
        m_execClient->setBreakpoint (fn, i.key(), true, i.value());
    }
}

void MainWindow::slotSearch()
{
    m_editorTab->selectAll(false);
    m_finder->show();
    m_finder->activateWindow();
    m_finder->findComboBox->setFocus();
}

void MainWindow::slotSearchNext()
{
    m_editorTab->searchNext();
}

void MainWindow::slotSearchPrevious()
{
    m_editorTab->searchPrev();
}

void MainWindow::slotGoto()
{
    m_editorTab->invokeGotoLine();
}

void MainWindow::slotGotoBrace() {
    //if (!m_editorTab->gotoBrace())
    //    QMessageBox::information(this,tr("GUIDE"),tr("No Matching brace is found."),QMessageBox::Ok);
    m_editorTab->gotoBrace();
}

void MainWindow::slotFindRequest (QString expr, bool re, bool cs, bool whole, bool forward)
{
    m_editorTab->search(expr, re, cs, whole, forward);
}

void MainWindow::slotReplaceRequest(QString srcexpr,QString desexpr,bool re, bool cs, bool whole, bool replaceAll) {
    m_editorTab->replace(srcexpr,desexpr,re,cs,whole,replaceAll);
}

void MainWindow::slotManageBreakpoints()
{
//    BkptsManager *m = new BkptsManager(this);
    BkptsManager *m = new BkptsManager(this);
    m->setAttribute(Qt::WA_DeleteOnClose);
    m->exec();
}

//void MainWindow::slotTable()
//{
//    BkptsManager *m = new BkptsManager(this);
//    m->exec();
//    delete m;
//}

void MainWindow::slotSettings()
{
    SettingDialog *set = new SettingDialog (this);
    connect (set, SIGNAL(applySettings()), this, SLOT(slotApplySettings()));
    if (set->exec() == QDialog::Accepted) {
    }
}

void MainWindow::slotApplySettings()
{
    MannaSettings* ss = MannaSettings::getMannaSettings();
    ss->applySettings();
    m_editorTab->setEditorProperties();
}

bool MainWindow::getCurrentFileNames(QString &fullname, QString &dirname, QString &filename, QString &exename)
{
    if (!m_editorTab->currentFileName(fullname))
        return false;
    if (fullname.isEmpty()) {
        return false;
    }
    QFileInfo finfo(fullname);
    filename = finfo.fileName();
    dirname = finfo.absoluteDir().absolutePath();
    //qDebug(filename.toLatin1().constData());

    exename = m_srcExeMap.value(fullname);

    QFileInfo exeInfo(dirname + "/" + exename);
    if (exename.isEmpty() || !exeInfo.exists()) {
        exename = filename.section(".", 0, -2);
#ifdef Q_OS_WIN
    exename += ".exe";
#endif
        //qDebug(exename.toLatin1().constData());

        QDir dir(dirname);
        bool changed = false;
        while (dir.entryList(QDir::Dirs).contains(exename, Qt::CaseInsensitive)) {
#ifdef Q_OS_WIN
            exename.insert(exename.length()-4, SUFFIX);
#else
            exename += SUFFIX;
#endif
            changed = true;
        }
        if (changed) {
            QMessageBox::warning (this, PROGRAM_NAME,
                QString (tr("Target file has been renamed as %1\n")).arg(exename),
                QMessageBox::Ok);
        }
        m_srcExeMap.insert(fullname, exename);
    }
    return true;
}

bool MainWindow::getCompileCmd(QString &cmdline, QString srcname, QString targetname)
{
    QString mingw, fpc, suffix;
    bool show;
    MannaSettings::getMannaSettings()->
            compilerPath(mingw, fpc, suffix, show);
    mingw += "/";
    fpc += "/";

    MannaSettings *settings = MannaSettings::getMannaSettings();
    ExternTool e;
    if (srcname.endsWith(".cpp", Qt::CaseInsensitive)) {
        if (!e.testGpp()) {
            QMessageBox::warning(this, PROGRAM_NAME,
                            tr("Can not find g++!"),
                            QMessageBox::Ok);
            return false;
        }
        settings->beginGroup("CompileCommands");
#ifdef Q_OS_WIN
        QString cc = settings->value("WIN_cpp", QVariant("\"%1g++\" -Wall -g -o \"%2\" \"%3\"")).toString();
#else
        QString cc = settings->value("ELSE_cpp", QVariant("\"%1g++\" -Wall -g -o \"%2\" \"%3\"")).toString();
#endif
        settings->endGroup();
        cmdline = cc.arg(mingw).arg(targetname).arg(srcname);
    } else if (srcname.endsWith(".c", Qt::CaseInsensitive)) {
        if (!e.testGcc()) {
            QMessageBox::warning(this, PROGRAM_NAME,
                            tr("Can not find gcc!"),
                            QMessageBox::Ok);
            return false;
        }
        settings->beginGroup("CompileCommands");
#ifdef Q_OS_WIN
        QString cc = settings->value("WIN_c", QVariant("\"%1gcc\" -Wall -g -o \"%2\" \"%3\"")).toString();
#else
        QString cc = settings->value("ELSE_c", QVariant("\"%1gcc\" -Wall -g -o \"%2\" \"%3\"")).toString();
#endif
        settings->endGroup();
        cmdline = cc.arg(mingw).arg(targetname).arg(srcname);
    } else if (srcname.endsWith(".pas", Qt::CaseInsensitive)) {
        if (!e.testFpc()) {
            QMessageBox::warning(this, PROGRAM_NAME,
                            tr("Can not find fpc!"),
                            QMessageBox::Ok);
            return false;
        }
        QString cc = settings->value("pas", QVariant("\"%1fpc\" -g \"%2\"")).toString();
        cmdline = cc.arg(fpc).arg(srcname);
    } else {
        QMessageBox::warning(this, PROGRAM_NAME,
                    tr("This file can not be compiled!\n"),
                    QMessageBox::Ok);
        return false;
    }
    return true;
}

void MainWindow::slotHelp()
{
    HelpWidget::instance()->showMaximized();
}

//void MainWindow::slotStackListChanged(QString fullfilename,QString funcname,int curline,int stackdepth) {
//    /*
//    if (stack_depth == -1) {
//        //stack_line = curline;
//        //stack_depth = stackdepth;
//        //stack_fullfilename = fullfilename;
//        //stack_funcname = funcname;
//        ////qDebug(stack_fullfilename.toLatin1().constData());
//        ////qDebug(stack_funcname.toLatin1().constData());
//    }
//    else {
//    }*/
//}

void MainWindow::changeRunState (RunState state)
{
    m_state = state;

    actionCompile->setEnabled (state == EditMode);
    actionStopCompile->setEnabled (state == CompileMode);
    actionExecute->setEnabled (state == EditMode);

    actionDebug->setEnabled (state == EditMode || state == DebugMode);
    actionStepOver->setEnabled (state == EditMode || state == DebugMode);

#ifdef Q_OS_LINUX
    actionPauseResume->setEnabled(false);
    actionStopExecute->setEnabled (state == ExecMode);
#else
    actionPauseResume->setEnabled(false);
    actionStopExecute->setEnabled(state == ExecMode);
#endif
    actionStopDebug->setEnabled (state == DebugMode);
    actionStepInto->setEnabled (state == DebugMode);
    //actionStepOver->setEnabled (state == DebugMode);
    actionRuntoCursor->setEnabled ( state == DebugMode);

    actionStepOut->setEnabled (state == DebugMode);

//    if (state != EditMode) {
//        dockOutputs->setVisible (true);
//        gdbOutputDock->setVisible(true);
//        callStackDock->setVisible(true);
//        treeLocalDock->setVisible(true);
//        treeWatchDock->setVisible(true);
//        memoryDock->setVisible(true);
//    }
    //dockCallStack->setVisible (state == DebugMode);
    //dockRegisters->setVisible (state == DebugMode);
    menuLanguage->setEnabled(state==EditMode);
}

bool MainWindow::getSourceType(SourceType &type, QString srcname)
{
    if (srcname.endsWith(".cpp", Qt::CaseInsensitive)) {
        type = TYPE_C_CPP;
    } else if (srcname.endsWith(".c", Qt::CaseInsensitive)) {
        type = TYPE_C_CPP;
    } else if (srcname.endsWith(".pas", Qt::CaseInsensitive)) {
        type = TYPE_PASCAL;
    } else {
        return false;
    }
    return true;
}

bool MainWindow::doOpenFile(const QString &file)
{
    bool retv;
    retv = (m_editorTab->openFile(file) >= 0);
    if (retv) {
        setRecentFile(file);

        MannaSettings* settings = MannaSettings::getMannaSettings();
        settings->beginGroup("OpenedFileList");
        QStringList files = settings->value("OpenedFiles").toStringList();
        files.removeAll(file);
        files.append(file);
        //qDebug(file.toLatin1().constData());
        settings->setValue("OpenedFiles", files);
        settings->endGroup();
    }
    return retv;
}

void MainWindow::slotItemDoubleClicked (QListWidgetItem * item)
{
    int line = item->data (Qt::UserRole).toInt ();

    m_editorTab->gotoLine (line);
}

bool MainWindow::userPrompt ()
{
    //qDebug("userPrompt");
    if (m_state == DebugMode)
    {
        MEditor * editor = m_editorTab->editor (m_activeFileName, true);
        if (m_lastModified < editor->lastModified ())
        {
            int ret = QMessageBox::warning (this, PROGRAM_NAME,
                    tr ("The source file has been modified, hence the following\n"
                    "information displayed may be incorrect.\n\n"
                    "Press Ok to continue debug anyway\n"
                    "Press Cancel to exit debug"),
                    QMessageBox::Ok | QMessageBox::Cancel,
                    QMessageBox::Cancel);

            if (ret == QMessageBox::Cancel)
            {
                stopDebug ();
                return true;
            }
        }
    }

    return false;
}

//bool MainWindow::getVarList(QString targetFullName) {     //m_varList = "";
//#ifdef Q_WS_WIN
//    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GBK"));
//#else
//    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
//#endif
//    //qebug(targetFullName.toAscii().constData());
//    FILE *fp = fopen(targetFullName.toAscii().constData(),"rb");
//    if (!fp)return false;
//    char* buffer = 0;
//    int buffer_len = 0;
//#ifdef Q_WS_WIN
//    IMAGE_DOS_HEADER  DosHeader;
//    IMAGE_NT_HEADERS  NTHeaders;
//    IMAGE_SECTION_HEADER secHeader;
//
//    fread(&DosHeader,sizeof(IMAGE_DOS_HEADER),1,fp);
//    fseek(fp,DosHeader.e_lfanew,SEEK_SET);
//    fread(&NTHeaders,sizeof(IMAGE_NT_HEADERS),1,fp);
//
//    for (int i = 0;i < NTHeaders.FileHeader.NumberOfSections;++i) {
//        fseek(fp,DosHeader.e_lfanew+sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER)*i,SEEK_SET);
//        fread(&secHeader,sizeof(IMAGE_SECTION_HEADER),1,fp);
//        if (!strncmp((char*)secHeader.Name,".stabstr",8)) {break;}
//    }
//    fseek(fp,secHeader.PointerToRawData,SEEK_SET);
//    buffer = (char*)malloc(sizeof(char)*secHeader.SizeOfRawData);
//    buffer_len = secHeader.SizeOfRawData;
//    fread(buffer,sizeof(char),secHeader.SizeOfRawData,fp);
//    for (int i = 0;i < secHeader.SizeOfRawData-1;++i) {
//        if (buffer[i] == 0)buffer[i] = ' ';
//    }
//#else
//    Elf32_Ehdr eheader;
//    fread(&eheader,sizeof(Elf32_Ehdr),1,fp);
//    fseek(fp,eheader.e_shoff,SEEK_SET);
//
//    Elf32_Shdr *sheaders;
//    sheaders = (Elf32_Shdr*)malloc(sizeof(Elf32_Shdr) * eheader.e_shnum);
//
//    fread(sheaders,sizeof(Elf32_Shdr),eheader.e_shnum,fp);
//
//    int stab_off = -1;
//
//    for (int i = 0;i < eheader.e_shnum;++i) {
//        if (sheaders[i].sh_type == 3) {
//            //char * buffer;
//            buffer = (char*)malloc(sizeof(char) * sheaders[i].sh_size);
//            fseek(fp,sheaders[i].sh_offset,SEEK_SET);
//            fread(buffer,sizeof(char),sheaders[i].sh_size,fp);
//            int j;
//            for (j = 0;j < sheaders[i].sh_size;++j) {
//                if (buffer[j] == 0x2E) {
//                    if (!strncmp(&buffer[j],".stabstr",8)) {
//                        stab_off = j;break;
//                    }
//                }
//            }
//            free(buffer);
//        }
//        if (stab_off > -1) {
//            break;
//        }
//    }
//    if (stab_off > -1) {
//        for (int i = 0;i < eheader.e_shnum;++i) {
//            if (sheaders[i].sh_name == stab_off) {
//                fseek(fp,sheaders[i].sh_offset,SEEK_SET);
//                buffer = (char*)malloc(sizeof(char)*sheaders[i].sh_size);
//                fread(buffer,sizeof(char),sheaders[i].sh_size,fp);
//                buffer_len = sheaders[i].sh_size;
//                for (int j = 0;j < sheaders[i].sh_size - 1;++j) {
//                    if (buffer[j] == 0)buffer[j] = ' ';
//                }
//                //qDebug(buffer);
//                break;
//            }
//        }
//    }
//
//#endif
//
//    if (buffer != 0 && buffer_len > 0) {
//        QString tbuff = buffer;
//        free(buffer);
//        //qDebug(tbuff.toLatin1().constData());
//        for (int j = tbuff.length()-1;j >= 0;--j) {
//            int k;
//            //if (tbuff[j] == ';' && tbuff[j-1] == ';')break;
//            if (tbuff[j] == ':') {
//                k = j;
//                QString temp;
//                if ((tbuff[j+1] >= '0' && tbuff[j+1] <= '9') || tbuff[j+1] == '(' || tbuff[j+1] == '-') {
//                    while (tbuff[--k] != ' '&& k >= 0);temp = tbuff.mid(k+1,j-k-1);
//                    if (temp.indexOf(QRegExp("[;|:|,|=]"),0) == -1) {
//                        m_varList += "/" + tbuff.mid(k+1,j-k-1);
//                    }
//                }
//                else if (tbuff[j+1] == 'a') {
//                    while (tbuff[--k] != ' '&& k >= 0);temp = tbuff.mid(k+1,j-k-1);
//                    if (temp.indexOf(QRegExp("[;|:|,|=]"),0) == -1) {
//                        m_varList += "/" + tbuff.mid(k+1,j-k-1);
//                    }
//                }
//                else if (tbuff[j+1] == 'b') {
//                    while (tbuff[--k] != ' '&& k >= 0);temp = tbuff.mid(k+1,j-k-1);
//                    if (temp.indexOf(QRegExp("[;|:|,|=]"),0) == -1) {
//                        m_varList += "/" + tbuff.mid(k+1,j-k-1);
//                    }
//                }
//                else if (tbuff[j+1] == 'c' || tbuff[j+1] == 'C') {
//                    while (tbuff[--k] != ' '&& k >= 0);temp = tbuff.mid(k+1,j-k-1);
//                    if (temp.indexOf(QRegExp("[;|:|,|=]"),0) == -1) {
//                        m_varList += "/" + tbuff.mid(k+1,j-k-1);
//                    }
//                }
//                else if (tbuff[j+1] == 'd' || tbuff[j+1] == 'D') {
//                    while (tbuff[--k] != ' '&& k >= 0);temp = tbuff.mid(k+1,j-k-1);
//                    if (temp.indexOf(QRegExp("[;|:|,|=]"),0) == -1) {
//                        m_varList += "/" + tbuff.mid(k+1,j-k-1);
//                    }
//                }
//                else if (tbuff[j+1] == 'G') {
//                    while (tbuff[--k] != ' '&& k >= 0);temp = tbuff.mid(k+1,j-k-1);
//                    if (temp.indexOf(QRegExp("[;|:|,|=]"),0) == -1) {
//                        m_varList += "/" + tbuff.mid(k+1,j-k-1);
//                    }
//                }
//                else if (tbuff[j+1] == 'p') {
//                    while (tbuff[--k] != ' '&& k >= 0);temp = tbuff.mid(k+1,j-k-1);
//                    if (temp.indexOf(QRegExp("[;|:|,|=]"),0) == -1) {
//                        m_varList += "/" + tbuff.mid(k+1,j-k-1);
//                    }
//                }
//                else if (tbuff[j+1] == 's' || tbuff[j+1] == 'S') {
//                    while (tbuff[--k] != ' '&& k >= 0);temp = tbuff.mid(k+1,j-k-1);
//                    if (temp.indexOf(QRegExp("[;|:|,|=]"),0) == -1) {
//                        m_varList += "/" + tbuff.mid(k+1,j-k-1);
//                    }
//                }
//                else if (tbuff[j+1] == 'v' || tbuff[j+1] == 'V') {
//                    while (tbuff[--k] != ' '&& k >= 0);temp = tbuff.mid(k+1,j-k-1);
//                    if (temp.indexOf(QRegExp("[;|:|,|=]"),0) == -1) {
//                        m_varList += "/" + tbuff.mid(k+1,j-k-1);
//                    }
//                }
//                else if (tbuff[j+1] == 'x') {
//                    while (tbuff[--k] != ' '&& k >= 0);temp = tbuff.mid(k+1,j-k-1);
//                    if (temp.indexOf(QRegExp("[;|:|,|=]"),0) == -1) {
//                        m_varList += "/" + tbuff.mid(k+1,j-k-1);
//                    }
//                }
//                j = k;
//            }
//        }
//        //qDebug("________________________________");
//        //qDebug(m_varList.toLatin1().constData());
//    }
//    fclose(fp);
//    return true;
//}
//
//
//bool MainWindow::isInVarList(QString str) {
//    //qDebug(str.toLatin1().constData());
//    QStringList myList = m_varList.split('/');
//    //qDebug(m_varList.toLatin1().constData());
//    for (int i = 0;i < myList.size();++i) {
//        //qDebug(myList[i].toLatin1().constData());
//        if (!QString::compare(str,myList[i],Qt::CaseInsensitive)) {
//            return true;
//        }
//    }
//    return false;
//}

void MainWindow::slotLanguageChinese() {
    //qDebug("Changed!");

    if (actionChinese->isChecked() && actionEnglish->isChecked()) {
        actionEnglish->setChecked(false);
        qApp->installTranslator(&m_myTranslator);
        qApp->installTranslator(&m_qtTranslator);
        retranslateUi(this);
        m_finder->retranslateUi(m_finder);
        m_variableClient->myRetranslateUi();
        reCreateStatusTips();
        m_fileBrowser->setWindowTitle(tr("File Browser"));
    }
    else if (!actionChinese->isChecked() && !actionEnglish->isChecked()) {
        actionChinese->setChecked(true);
        /*
        qApp->removeTranslator(&translator);
        retranslateUi(this);
        m_variableClient->myRetranslateUi();
        m_fileBrowser->setWindowTitle(tr("File Browser"));
        */
    }
}

void MainWindow::slotLanguageEnglish() {
    //qDebug("Changed!");

    if (actionEnglish->isChecked() && actionChinese->isChecked()) {
        actionChinese->setChecked(false);
        qApp->removeTranslator(&m_myTranslator);
        qApp->removeTranslator(&m_qtTranslator);
        retranslateUi(this);
        m_finder->retranslateUi(m_finder);
        m_variableClient->myRetranslateUi();
        reCreateStatusTips();
        m_fileBrowser->setWindowTitle(tr("File Browser"));

    }
    else if (!actionEnglish->isChecked() && !actionChinese->isChecked()) {
        actionEnglish->setChecked(true);
        /*
        qApp->installTranslator(&translator);
        retranslateUi(this);
        m_variableClient->myRetranslateUi();
        m_fileBrowser->setWindowTitle(tr("File Browser"));
        */
    }
    /*
    if (actionEnglish->isChecked()) {
        actionChinese
        qApp->removeTranslator(&translator);
        retranslateUi(this);
        m_variableClient->myRetranslateUi();
        m_fileBrowser->setWindowTitle(tr("File Browser"));
    } else {
        qApp->installTranslator(&translator);
        retranslateUi(this);
        m_variableClient->myRetranslateUi();
        m_fileBrowser->setWindowTitle(tr("File Browser"));
    }
    */

}

void MainWindow::setButtonState(int flag) {

    if (flag == 0) {
        //if now the debug process is running ,the current step position is to be changes.the stepmark is also clear before the debug process is temporarily stopped.
        MEditor * editor = m_editorTab->editor (m_activeFileName, true);
        editor->setStepMarker ();
    }

    if (flag == 0) {
        actionDebug->setEnabled (false);
        actionStepOver->setEnabled (false);
        actionStepInto->setEnabled (false);
        actionRuntoCursor->setEnabled (false);
        actionStepOut->setEnabled (false);
    }
    else if (flag == 1) {
        actionDebug->setEnabled (true);
        actionStepOver->setEnabled (true);
        actionStepInto->setEnabled (true);
        actionRuntoCursor->setEnabled (true);
        actionStepOut->setEnabled (true);
        activateWindow();
    }
}

void MainWindow::onTargetStop (QString msg) {

    MEditor * editor = m_editorTab->editor (m_activeFileName, true);
    qDebug("find the current editor");
    if (editor)
    {
        m_editorTab->setCurrentWidget (editor);
        editor->setStepMarker (lastStepLine);
    }

    if (msg.contains("the outermost frame")) {
        QMessageBox::warning (this, PROGRAM_NAME,tr("GUIDE can't step out of the main function!"),QMessageBox::Ok,QMessageBox::Cancel);
    }
    else if (msg.contains("not being run") || msg.contains("not running") ) {
    QMessageBox::warning (this, PROGRAM_NAME,tr("An segment error occured!Please stop the debug process and check your source code."),QMessageBox::Ok,QMessageBox::Cancel);
        // stopDebug();
   }
    else {
    QMessageBox::warning (this, PROGRAM_NAME,msg,QMessageBox::Ok,QMessageBox::Cancel);
   }


    setButtonState(1);
}

void MainWindow::onTargetStop () {
    setButtonState(1);
}

void MainWindow::keyPressEvent(QKeyEvent *event) {

    MEditor * editor = NULL;
    QString str = "";
    QString fullname;

    switch(event->key()) {
        case Qt::Key_Delete:
            if (treeWatchWidget->hasFocus()) {
                //qDebug("Key_Delete");
                slotRemoveWatch();
            }
            break;
        case Qt::Key_F4:
            //qDebug("Key_shift ctrl a");
            //messageTabWidget->setCurrentWidget(debugWatchTab);
            treeWatchDock->raise();
            if (m_editorTab->currentFileName(fullname)) {
                editor = m_editorTab->editor (fullname, true);
                str = editor->getCurLine();
                slotAddWatch(str);
            } else {
                slotAddWatch();
            }
            break;
        default:QWidget::keyPressEvent(event);
    }
}

#ifdef Q_OS_WIN
bool MainWindow::winEvent(MSG *msg, long * /*result*/)
{
    QString fileName;
    char buffer[512];
    switch(msg->message)
    {
    case (WM_COPYDATA):
        COPYDATASTRUCT *cpd;
        cpd = (COPYDATASTRUCT*)(msg->lParam);
        memset(buffer,0,512*sizeof(char));
        strncpy(buffer,(char *)cpd->lpData,cpd->cbData);
        qDebug(buffer);
        fileName = QString::fromLocal8Bit(buffer);

        fileName.replace('\\', '/');
        this->activateWindow();
        QApplication::setActiveWindow( this );
        this->showMaximized ();
        doOpenFile(fileName);
        break;
    default:
        break;
    }
    return false;
}

#else

void closePipe( int fd ) {
    close(fd);
}

void MainWindow::slotlinuxMsg() {
    int fd;
    char buffer[FILE_MAXLENGTH+1];
    QString path = getMannaPath();
    path += "comm";
    if ((fd = open(path.toLocal8Bit().constData(), O_RDONLY | O_NONBLOCK,0)) == -1) {
        return;
    }
    memset(buffer,0,sizeof(char)*(FILE_MAXLENGTH+1));
    while (read(fd,buffer,sizeof(char)*FILE_MAXLENGTH)) {
        QString fileName = buffer;
        if (QFile::exists(fileName)) {
            doOpenFile(fileName);
        }
    }
    closePipe(fd);
    unlink(path.toLocal8Bit().constData());
}
#endif

void MainWindow::dragEnterEvent ( QDragEnterEvent * event ) {
    //qDebug("drag detected!");
    if (event->mimeData()->hasFormat("text/uri-list")) {
        event->acceptProposedAction();
    }
}

void MainWindow::dropEvent( QDropEvent *event ) {
    //qDebug("droped!");
    QList<QUrl> urls = event->mimeData()->urls();
    if (urls.isEmpty()) return;
    for (int i = 0;i < urls.count();++i) {
        QString fileName = urls.at(i).toLocalFile();
        if (fileName.isEmpty()) return;
        doOpenFile(fileName);
    }
}

void MainWindow::resetExternTool() {
    qApp->processEvents();
    ExternTool::resetExternTool();
    return;
}

void MainWindow::slotShowMemory()
{
    m_memoryClient->showMemory();
}

void MainWindow::slotSearchHelpFile()
{
    HelpWidget::instance()->slotSearch(m_searchKey->text());
    HelpWidget::instance()->showMaximized();
}
